﻿using System;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;

namespace Core.Experiment.Anim
{
    public partial class EasyAnimCtl
    {
        private class State : Component
        {
            public EasyAnimCtl Ctl { get; private set; }
            public bool IsDefault { get; private set; }

            public void SetDefault(bool isDefault) => IsDefault = isDefault;

            public string AnimPath { get; private set; }
            public string AnimName { get; private set; }
            public AnimationClip Clip { get; private set; }

            public float Weight { get; private set; }
            public float SetWeight(float weight) => Weight = weight;

            public bool IsFadeOut { get; private set; }
            public bool IsFadeIn { get; private set; }
            public bool IsStateOut { get; private set; }
            public bool IsStateIn { get; private set; }
            public bool IsPlaying { get; private set; }

            public float Length { get; private set; }
            public bool IsLoop { get; private set; }

            public ELayer Layer { get; private set; }

            public Action<State> StartEvt;
            public Action<State> EndEvt;

            public Action StartCallBackEvt;
            private AnimationClipPlayable mClipPlayable;

            private float elapsedTime;


            public void New(string animPath, string animName, AnimationClip clip, int layer)
            {
                AnimPath = animPath;
                AnimName = animName;
                Clip = clip;

                Length = clip.length;
                IsLoop = clip.isLooping;

                Layer = (ELayer)layer;
            }

            public void Attach(EasyAnimCtl ctl)
            {
                Ctl = ctl;

                mClipPlayable = AnimationClipPlayable.Create(ctl.mGraph, Clip);

                ctl.mMixerArray[(int)Layer].AddInput(mClipPlayable, 0);
            }

            public void Play(bool isFade = true, float time = 0)
            {
                StateIn(isFade, time);
            }

            public void Pause(float time)
            {
                mClipPlayable.SetTime(time * Length);
                mClipPlayable.Pause();
            }

            public void StateOut(bool isFade = true)
            {
                IsStateOut = true;
                IsStateIn = false;
                if (isFade)
                {
                    IsFadeOut = true;
                    IsFadeIn = false;
                }
                else
                {
                    IsFadeOut = false;
                    IsFadeIn = false;
                }
            }

            public void StateIn(bool isFade = true, float time = 0)
            {
                //Debug.LogError($"State.FadeIn name={AnimName}");
                IsStateOut = false;
                IsStateIn = true;
                if (isFade)
                {
                    IsFadeIn = true;
                    IsFadeOut = false;
                }
                else
                {
                    IsFadeIn = false;
                    IsFadeOut = false;
                }
                elapsedTime = time;

                IsPlaying = true;
                mClipPlayable.SetTime(time);
                mClipPlayable.Play();
                StartEvt?.Invoke(this);
                StartCallBackEvt?.Invoke();

            }

            public void Update()
            {
                if (IsPlaying)
                {
                    elapsedTime += Time.deltaTime;
                    if (elapsedTime >= Length)
                    {
                        elapsedTime = 0;

                        if (IsLoop)
                        {
                            if (!IsStateOut)
                            {
                                //EndEvt?.Invoke(this);
                                StartEvt?.Invoke(this);
                            }
                        }
                        else
                        {
                            mClipPlayable.Pause();
                            IsPlaying = false;
                            EndEvt?.Invoke(this);
                        }
                    }
                }

                if (IsStateOut)
                {
                    if (IsFadeOut)
                    {
                        Weight -= Time.deltaTime / Ctl.TransitionTime;
                        if (Weight <= 0)
                        {
                            IsFadeOut = false;
                            IsStateOut = false;
                            Weight = 0;

                            if (IsPlaying)
                            {
                                mClipPlayable.Pause();
                                IsPlaying = false;
                                elapsedTime = 0;
                                EndEvt?.Invoke(this);
                            }

                            //Debug.LogError($"anim_name={AnimName} 完成淡出");
                        }
                    }
                    else
                    {
                        Weight = 0;
                        IsFadeOut = false;
                        IsStateOut = false;
                        Weight = 0;

                        if (IsPlaying)
                        {
                            mClipPlayable.Pause();
                            IsPlaying = false;
                            elapsedTime = 0;
                            EndEvt?.Invoke(this);
                        }
                    }
                }

                if (IsStateIn)
                {
                    if (IsFadeIn)
                    {
                        if (Weight >= 1)
                        {
                            IsFadeIn = false;
                            IsStateIn = false;
                        }
                    }
                    else
                    {
                        if (Weight >= 1)
                        {
                            IsFadeIn = false;
                            IsStateIn = false;
                        }
                    }
                }
            }

            public override void Dispose()
            {
                if (IsDisposed) return;
                base.Dispose();

                StartEvt = null;
                EndEvt = null;
                StartCallBackEvt = null;
                IsDefault = false;
                AnimPath = string.Empty;
                AnimName = string.Empty;
                Clip = null;
                Weight = 0;
                Layer = 0;
            }
        }
    }

}
